#ifndef __TREECLASSIFIER__
#define __TREECLASSIFIER__


//#include "SDLittleDog.h"
//#include "SDSlowWalk.h"
//#include "SDVectorOp.h"
#include <iostream>
#include <ctime>
#include <stdlib.h>
#include <cstdlib>
#include <math.h>
#include <vector>
#include <fstream>
#include <stdio.h>
#include <utility>
#include <stack>
#include <queue>
#include <set>

using namespace std;

struct TreeNode{
    public:
        int feature;
        float tolerance;
        TreeNode* childL;
        TreeNode* childR;
        float p;

        TreeNode(){
             feature = -1;
             tolerance = -1;
             p = -1;
             childL = NULL;
             childR = NULL;
        }
};

struct TempTreeNode{
    public:
        int index;
        vector<bool>* dataFlow; //indicates which data points flow through this node
        TreeNode node;
        int good;
        int bad;
        TempTreeNode* left;
        TempTreeNode* right;

        TempTreeNode(){
             index = -1;
             good = 0;
             bad = 0;
             left = NULL;
             right = NULL;
             dataFlow = new vector<bool>();
        }
};

class smallest_f // comparison function for feature arrays
{
public:
  bool operator() (vector<float> lhs, vector<float> rhs) const
  {
      int size = lhs.size();
      for(int i = 1; i < size; i++){
            if(lhs.at(i) < rhs.at(i)) return true;
      }
      return false;
  }
};

class TreeClassifier{

    public:
        static string classifierFileName;
        TreeClassifier(string fileName, bool existingClassifier);
        bool is_loaded();
        float classify(vector<float>* costs);

    //private:
        TreeNode* classifierRoot;
        bool correctlyLoaded;
        int numberOfFeatures;
        vector<vector<float> > trainingFeatures; //numFeatures
        vector<int> trainingOutcomes;
        vector<vector<float> > testingFeatures; //numFeatures
        vector<int> testingOutcomes;
        vector<vector<float> > tolerances;
        const static int numTols = 10;
        const static float percentTraining = .9; //Determines what percent, roughly, of data will go to the training set as opposed to the testing set.
        void GenerateClassifier(string fileName);
        void LoadClassifier();
        int Split(TempTreeNode* node, int* nodeIndexer);
        void PrintNodesToFile(ofstream* writer, TempTreeNode* node);
        float CalculateProbability(int target, int other);
        float h_val(int good, int bad);
        float h(TempTreeNode* node);
        void TestClassifier();
        float FollowTree(vector<float>* costs, TreeNode* node);
        void InitializeTempTreeNode(TempTreeNode* node, int* indexer, int good, int bad, vector<bool>* flow);
        //DEBUGGING FUNCTIONS
        void DisplayVector(vector<float> vect);
        void DisplayTempTreeNode(TempTreeNode* node);
        void DisplayTreeNode(TreeNode* node);
        void DisplayTolerances();
};

#endif
